﻿using System;
using System.Collections.Generic;
using System.Threading;

#if WINDOWS_PHONE
namespace Fibre.WP7.Threading
#else
#if SILVERLIGHT
namespace Fibre.Silverlight.Threading
#else
namespace Fibre.Threading
#endif
#endif
{
    /// <summary>
    /// Builder class for work items
    /// </summary>
    internal class WorkItemBuilder : WorkItemBuilder<object>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="WorkItemBuilder"/> class.
        /// </summary>
        /// <param name="work">The work to perform.</param>
        public WorkItemBuilder(Action work)
            : base(()=>
                       {
                           work();
                           return null;
                       })
        {}
    }

    /// <summary>
    /// Builder class for work items
    /// </summary>
    /// <typeparam name="T">Result type</typeparam>
    public class WorkItemBuilder<T>
    {
        private readonly Func<AsyncCallback, IAsyncResult> _work;
        private readonly List<Action<IAsyncResult>> _completedEvents = new List<Action<IAsyncResult>>();
        private AsyncResult<T> _result;

        /// <summary>
        /// Initializes a new instance of the <see cref="WorkItemBuilder&lt;TResult&gt;"/> class.
        /// </summary>
        /// <param name="work">The work.</param>
        public WorkItemBuilder(Func<T> work)
        {
            _work = callback =>
            {
                _result = new AsyncResult<T>(callback, null);
                ThreadPool.QueueUserWorkItem(state =>
                {
                    try
                    {
                        _result.Complete(work(), false);
                    }
                    catch (Exception ex)
                    {
                        _result.HandleException(ex, false);
                    }
                });
                return _result;
            };
        }

        /// <summary>
        /// Adds a complete callback.
        /// </summary>
        /// <param name="onComplete">The on complete callback.</param>
        /// <returns></returns>
        public WorkItemBuilder<T> AddCompleteHandler(Action<AsyncResult<T>> onComplete)
        {
            _completedEvents.Add(results => onComplete((AsyncResult<T>)results));
            return this;
        }

        /// <summary>
        /// Builds the work item.
        /// </summary>
        /// <returns>The Work Item</returns>
        public WorkItem BuildWorkItem()
        {
            var buildWorkItem = new WorkItem
            {
                Work = _work
            };
            buildWorkItem.CompletedEvents.AddRange(_completedEvents);
            return buildWorkItem;
        }
    }
}
